package com.pulse.common.utils.sor;

public class Crc16Ccitt {
    private int polynomial;      // 多项式
    private int[] table;         // CRC 表
    private int crc;             // 当前 CRC 值
    private int finalXorValue;   // 最终异或值
    private boolean reflectInput;  // 是否反射输入
    private boolean reflectOutput; // 是否反射输出

    /**
     * 默认构造函数，使用标准 CRC16-CCITT 参数：
     * - 多项式: 0x1021
     * - 初始值: 0xFFFF
     * - 输入反射: false
     * - 输出反射: false
     * - 最终异或值: 0x0000
     */
    public Crc16Ccitt() {
        this(0x1021, 0xFFFF, false, false, 0x0000);
    }

    /**
     * 自定义参数的构造函数
     *
     * @param polynomial     多项式
     * @param initialValue   初始值
     * @param reflectInput   是否反射输入
     * @param reflectOutput  是否反射输出
     * @param finalXorValue  最终异或值
     */
    public Crc16Ccitt(int polynomial, int initialValue, boolean reflectInput, boolean reflectOutput, int finalXorValue) {
        this.polynomial = polynomial;
        this.crc = initialValue;
        this.reflectInput = reflectInput;
        this.reflectOutput = reflectOutput;
        this.finalXorValue = finalXorValue;
        this.table = new int[256];
        initializeTable();
    }

    /**
     * 初始化 CRC 表
     */
    private void initializeTable() {
        for (int i = 0; i < table.length; i++) {
            int value = i;
            if (reflectInput) {
                value = reflect(value, 8);
            }
            value <<= 8;
            for (int j = 0; j < 8; j++) {
                if ((value & 0x8000) != 0) {
                    value = (value << 1) ^ polynomial;
                } else {
                    value <<= 1;
                }
            }
            if (reflectOutput) {
                value = reflect(value, 16);
            }
            table[i] = value;
        }
    }

    /**
     * 反射数据
     *
     * @param data   数据
     * @param nBits  位数
     * @return 反射后的数据
     */
    private int reflect(int data, int nBits) {
        int reflection = 0;
        for (int bit = 0; bit < nBits; bit++) {
            if ((data & 0x01) != 0) {
                reflection |= (1 << ((nBits - 1) - bit));
            }
            data >>>= 1; // 无符号右移
        }
        return reflection;
    }

    /**
     * 更新 CRC 值
     *
     * @param bytes  字节数组
     * @param offset 起始偏移量
     * @param length 长度
     */
    public void update(byte[] bytes, int offset, int length) {
        if (reflectInput) {
            for (int i = offset; i < offset + length; i++) {
                int index = (crc ^ (bytes[i] & 0xFF)) & 0xFF;
                crc = (crc >>> 8) ^ table[index];
            }
        } else {
            for (int i = offset; i < offset + length; i++) {
                int index = ((crc >>> 8) ^ (bytes[i] & 0xFF)) & 0xFF;
                crc = (crc << 8) ^ table[index];
            }
        }
    }

    /**
     * 获取当前的 CRC 校验和
     *
     * @return CRC 校验和
     */
    public int getChecksum() {
        return (crc ^ finalXorValue) & 0xFFFF; // 确保返回16位
    }

    /**
     * 重置 CRC 值为初始值
     */
    public void reset() {
        crc = 0xFFFF; // 重置为初始值
    }
}
